package operation

import (
	"../common"
	"../web"
	"encoding/json"
	"regexp"
	"strconv"
	"strings"
)

type OperKeyPartsObj struct {
	common.BaseHandler
}

func (self *OperKeyPartsObj) ParameterCheck() bool {
	s_ssns := strings.TrimSpace(self.Ctx.Params["ssn"])
	s_wono := self.Ctx.Params["wono"]
	s_stat := self.Ctx.Params["station"]
	s_line := self.Ctx.Params["line"]
	s_item := self.Ctx.Params["item"]
	s_fcod := self.Ctx.Params["failcode"]

	err := ""
	status := common.GetScanStatus(self.Ctx, s_stat)
	if !status {
		err = common.GetText(self.Lang, "System is busy, please wait a moment and try again.")
	}

	s_pt01 := strings.TrimSpace(self.Ctx.Params["part1"])
	s_pt02 := strings.TrimSpace(self.Ctx.Params["part2"])
	s_pt03 := strings.TrimSpace(self.Ctx.Params["part3"])
	s_pt04 := strings.TrimSpace(self.Ctx.Params["part4"])
	s_pt05 := strings.TrimSpace(self.Ctx.Params["part5"])
	s_pt06 := strings.TrimSpace(self.Ctx.Params["part6"])
	s_pt07 := strings.TrimSpace(self.Ctx.Params["part7"])
	s_pt08 := strings.TrimSpace(self.Ctx.Params["part8"])
	s_pt09 := strings.TrimSpace(self.Ctx.Params["part9"])
	s_pt10 := strings.TrimSpace(self.Ctx.Params["part10"])

	parts_all := make(map[string]int)
	if v, ok := parts_all[s_pt01]; ok {
		parts_all[s_pt01] = v + 1
	} else {
		parts_all[s_pt01] = 1
	}
	if v, ok := parts_all[s_pt02]; ok {
		parts_all[s_pt02] = v + 1
	} else {
		parts_all[s_pt02] = 1
	}
	if v, ok := parts_all[s_pt03]; ok {
		parts_all[s_pt03] = v + 1
	} else {
		parts_all[s_pt03] = 1
	}
	if v, ok := parts_all[s_pt04]; ok {
		parts_all[s_pt04] = v + 1
	} else {
		parts_all[s_pt04] = 1
	}
	if v, ok := parts_all[s_pt05]; ok {
		parts_all[s_pt05] = v + 1
	} else {
		parts_all[s_pt05] = 1
	}
	if v, ok := parts_all[s_pt06]; ok {
		parts_all[s_pt06] = v + 1
	} else {
		parts_all[s_pt06] = 1
	}
	if v, ok := parts_all[s_pt07]; ok {
		parts_all[s_pt07] = v + 1
	} else {
		parts_all[s_pt07] = 1
	}
	if v, ok := parts_all[s_pt08]; ok {
		parts_all[s_pt08] = v + 1
	} else {
		parts_all[s_pt08] = 1
	}
	if v, ok := parts_all[s_pt09]; ok {
		parts_all[s_pt09] = v + 1
	} else {
		parts_all[s_pt09] = 1
	}
	if v, ok := parts_all[s_pt10]; ok {
		parts_all[s_pt10] = v + 1
	} else {
		parts_all[s_pt10] = 1
	}

	for k, v := range parts_all {
		if v > 1 && k != "" {
			err = common.GetText(self.Lang, "Component serial number can not be repeated.")
			break
		}
	}

	if err == "" && s_ssns == "" {
		err = common.GetText(self.Lang, "Please input the Product No.")
	}

	if err == "" {
		if _, ok := parts_all[s_ssns]; ok {
			err = common.GetText(self.Lang, "Component serial same as the Product No.")
		}
	}

	if err == "" {
		sRtnData := *common.FetchAllRowsPtr(
			`SELECT ROW_NUMBER() OVER(ORDER BY IDX), PARTNAME, ISNULL(BARCODE, ''), LENG 
          	   FROM SFC_PARTSETTING(NOLOCK) 
         	  WHERE ITEM=? 
           		AND STATION=?`,
			self.Usr.Conn, new(common.PartDetail), s_item, s_stat)
		for _, val := range sRtnData {
			iIndex := val.(common.PartDetail).Index
			s_ptnm := val.(common.PartDetail).Name
			s_barc := val.(common.PartDetail).Barcod
			s_leng := val.(common.PartDetail).Leng
			switch {
			case iIndex == 1:
				if !chkKeyPartsValid(s_pt01, []string{s_barc, s_leng}) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] is invalid.", s_ptnm, s_pt01)
					break
				}
				if !chkCompleteProcess(s_pt01, s_item) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] didnt complete the process.", s_ptnm, s_pt01)
					break
				}
			case iIndex == 2:
				if !chkKeyPartsValid(s_pt02, []string{s_barc, s_leng}) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] is invalid.", s_ptnm, s_pt02)
					break
				}
				if !chkCompleteProcess(s_pt02, s_item) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] didnt complete the process.", s_ptnm, s_pt02)
					break
				}
			case iIndex == 3:
				if !chkKeyPartsValid(s_pt03, []string{s_barc, s_leng}) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] is invalid.", s_ptnm, s_pt03)
					break
				}
				if !chkCompleteProcess(s_pt03, s_item) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] didnt complete the process.", s_ptnm, s_pt03)
					break
				}
			case iIndex == 4:
				if !chkKeyPartsValid(s_pt04, []string{s_barc, s_leng}) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] is invalid.", s_ptnm, s_pt04)
					break
				}
				if !chkCompleteProcess(s_pt04, s_item) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] didnt complete the process.", s_ptnm, s_pt04)
					break
				}
			case iIndex == 5:
				if !chkKeyPartsValid(s_pt05, []string{s_barc, s_leng}) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] is invalid.", s_ptnm, s_pt05)
					break
				}
				if !chkCompleteProcess(s_pt05, s_item) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] didnt complete the process.", s_ptnm, s_pt05)
					break
				}
			case iIndex == 6:
				if !chkKeyPartsValid(s_pt06, []string{s_barc, s_leng}) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] is invalid.", s_ptnm, s_pt06)
					break
				}
				if !chkCompleteProcess(s_pt06, s_item) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] didnt complete the process.", s_ptnm, s_pt06)
					break
				}
			case iIndex == 7:
				if !chkKeyPartsValid(s_pt07, []string{s_barc, s_leng}) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] is invalid.", s_ptnm, s_pt07)
					break
				}
				if !chkCompleteProcess(s_pt07, s_item) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] didnt complete the process.", s_ptnm, s_pt07)
					break
				}
			case iIndex == 8:
				if !chkKeyPartsValid(s_pt08, []string{s_barc, s_leng}) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] is invalid.", s_ptnm, s_pt08)
					break
				}
				if !chkCompleteProcess(s_pt08, s_item) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] didnt complete the process.", s_ptnm, s_pt08)
					break
				}
			case iIndex == 9:
				if !chkKeyPartsValid(s_pt09, []string{s_barc, s_leng}) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] is invalid.", s_ptnm, s_pt09)
					break
				}
				if !chkCompleteProcess(s_pt09, s_item) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] didnt complete the process.", s_ptnm, s_pt09)
					break
				}
			case iIndex == 10:
				if !chkKeyPartsValid(s_pt10, []string{s_barc, s_leng}) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] is invalid.", s_ptnm, s_pt10)
					break
				}
				if !chkCompleteProcess(s_pt10, s_item) {
					err = common.GetText(self.Lang, "[ %v ]: [%v] didnt complete the process.", s_ptnm, s_pt10)
					break
				}
			}
		}
	}

	if err != "" {
		iRtnData := *common.FetchOneRowPtr(
			`SELECT TOP 1 ISNULL(PASSED, 0) 
           	   FROM SFC_PASSED(NOLOCK) 
          	  WHERE WONO=? 
            	AND STATION=?`,
			self.Usr.Conn, new(common.RecDataStr), s_wono, s_stat)
		passedqty := iRtnData.(common.RecDataStr).Data

		dict_js, _ := json.Marshal(map[string]string{"result": err, "passedqty": passedqty})
		self.Ctx.ResponseWriter.Write(dict_js)
		return false
	}

	self.Sqlparas = append(self.Sqlparas, s_ssns)
	self.Sqlparas = append(self.Sqlparas, s_wono)
	self.Sqlparas = append(self.Sqlparas, s_stat)
	self.Sqlparas = append(self.Sqlparas, s_line)
	self.Sqlparas = append(self.Sqlparas, s_item)
	self.Sqlparas = append(self.Sqlparas, s_fcod)
	self.Sqlparas = append(self.Sqlparas, s_pt01)
	self.Sqlparas = append(self.Sqlparas, s_pt02)
	self.Sqlparas = append(self.Sqlparas, s_pt03)
	self.Sqlparas = append(self.Sqlparas, s_pt04)
	self.Sqlparas = append(self.Sqlparas, s_pt05)
	self.Sqlparas = append(self.Sqlparas, s_pt06)
	self.Sqlparas = append(self.Sqlparas, s_pt07)
	self.Sqlparas = append(self.Sqlparas, s_pt08)
	self.Sqlparas = append(self.Sqlparas, s_pt09)
	self.Sqlparas = append(self.Sqlparas, s_pt10)
	self.Sqlparas = append(self.Sqlparas, self.Usr.Username)

	return true
}

func (self *OperKeyPartsObj) SqlQueryExecute() {
	s_ssns := self.Sqlparas[0].(string)
	s_wono := self.Sqlparas[1].(string)
	s_stat := self.Sqlparas[2].(string)
	s_item := self.Sqlparas[4].(string)
	s_fcod := self.Sqlparas[5].(string)
	common.SetScanStatus(self.Ctx, s_stat, false)
	spRtnData := *common.FetchOneRowPtr(
		`sp_SSNKeyPartsScan ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?`,
		self.Usr.Conn, new(common.SPReturn), self.Sqlparas...)
	common.SetScanStatus(self.Ctx, s_stat, true)
	err := common.GetTextSP(self.Lang, spRtnData)

	iRtnData := *common.FetchOneRowPtr(
		`SELECT TOP 1 ISNULL(PASSED, 0) 
           FROM SFC_PASSED(NOLOCK) 
          WHERE WONO=? 
            AND STATION=?`,
		self.Usr.Conn, new(common.RecDataStr), s_wono, s_stat)
	passedqty := iRtnData.(common.RecDataStr).Data

	if spRtnData.(common.SPReturn).Flag == 0 || spRtnData.(common.SPReturn).Flag == 999 {
		if s_fcod == "" {
			spRtnData = *common.FetchOneRowPtr(
				`sp_SSNKeyPartsRollBack ?, ?, ?, ?`,
				self.Usr.Conn, new(common.SPReturn), s_ssns, s_wono, s_item, s_stat)
			if spRtnData.(common.SPReturn).Flag > 0 {
				err = common.GetTextSP(self.Lang, spRtnData)
			}
		}
	}

	dict_js, _ := json.Marshal(map[string]string{"result": err, "passedqty": passedqty})
	self.Ctx.ResponseWriter.Write(dict_js)
}

func KeyPartsScanHandler(ctx *web.Context) {
	self := new(OperKeyPartsObj)
	self.Ctx = ctx
	self.DoJson(self)
}

func chkCompleteProcess(prod, item string) bool {
	conn := ""
	sRtnData := *common.FetchOneRowPtr(
		`SELECT TOP 1 CURR_STATION 
		   FROM SFC_SSN(NOLOCK) 
		  WHERE SSN_NO=?`,
		common.Prd01, new(common.RecDataStr), prod)
	station := sRtnData.(common.RecDataStr).Data
	if station != "" {
		conn = common.Prd01
	}

	if conn == "" {
		sRtnData = *common.FetchOneRowPtr(
			`SELECT TOP 1 CURR_STATION 
			   FROM SFC_SSN(NOLOCK) 
			  WHERE SSN_NO=?`,
			common.Prd02, new(common.RecDataStr), prod)
		station = sRtnData.(common.RecDataStr).Data
		if station != "" {
			conn = common.Prd02
		}
	}
	if conn == "" {
		sRtnData = *common.FetchOneRowPtr(
			`SELECT TOP 1 CURR_STATION 
			   FROM SFC_SSN(NOLOCK) 
			  WHERE SSN_NO=?`,
			common.Prd03, new(common.RecDataStr), prod)
		station = sRtnData.(common.RecDataStr).Data
		if station != "" {
			conn = common.Prd03
		}
	}
	if conn == "" {
		sRtnData = *common.FetchOneRowPtr(
			`SELECT TOP 1 CURR_STATION 
			   FROM SFC_SSN(NOLOCK) 
			  WHERE SSN_NO=?`,
			common.Prd05, new(common.RecDataStr), prod)
		station = sRtnData.(common.RecDataStr).Data
		if station != "" {
			conn = common.Prd05
		}
	}
	if conn == "" {
		sRtnData = *common.FetchOneRowPtr(
			`SELECT TOP 1 CURR_STATION 
			   FROM SFC_SSN(NOLOCK) 
			  WHERE SSN_NO=?`,
			common.Prd06, new(common.RecDataStr), prod)
		station = sRtnData.(common.RecDataStr).Data
		if station != "" {
			conn = common.Prd06
		}
	}

	if conn == "" {
		return true
	}

	values := *common.FetchOneRowPtr(
		`SELECT ITEM, STATION 
		   FROM SFC_ASSEMBLYSET(NOLOCK)
		  WHERE ITEM=?`,
		conn, new(common.AssemblySet), item)
	setsta := strings.TrimSpace(values.(common.AssemblySet).Station)
	if station != "SFCF" {
		if setsta != "" {
			if setsta != station {
				return false
			} else {
				return true
			}
		}
		return false
	}
	return true
}

func chkKeyPartsValid(part string, sets []string) bool {
	chr_pattern := `[^\d{1}]`
	num_pattern := `\d{1}`
	any_pattern := `.{1}`

	s_barc := sets[0]
	s_leng := sets[1]

	part = strings.TrimSpace(part)
	if part == "" {
		return false
	}

	i_len, _ := strconv.Atoi(s_leng)
	if i_len != -1 && len(part) != i_len {
		return false
	}

	if s_barc != "" && len(part) != len(s_barc) {
		return false
	}

	s_barc = strings.ToUpper(s_barc)
	s_barc = strings.TrimSpace(s_barc)
	part = strings.ToUpper(part)

	if s_barc != "" {
		c_barc := strings.Replace(s_barc, "#", chr_pattern, -1)
		c_barc = strings.Replace(c_barc, "$", num_pattern, -1)
		c_barc = strings.Replace(c_barc, "&", any_pattern, -1)

		if m, _ := regexp.MatchString(c_barc, part); !m {
			return false
		}
	}

	return true
}
